package cn.aishua.util;

import java.lang.ref.WeakReference;
import java.util.LinkedHashMap;

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
import android.util.Log;

public class MemoryCache
{
    private static final int SOFT_CACHE_CAPACITY = 40;

    private final int hardCachedSize = 6 * 1024 * 1024;
    private static MemoryCache instance;

    private MemoryCache()
    {
    }

    public synchronized static MemoryCache getInstance()
    {
        if( instance == null )
            instance = new MemoryCache();
        return instance;
    }

    private final LinkedHashMap<String, WeakReference<Bitmap>> sSoftBitmapCache = new LinkedHashMap<String, WeakReference<Bitmap>>(
        SOFT_CACHE_CAPACITY, 0.75f, true )
    {

        private static final long serialVersionUID = 1044354129808468403L;

        @Override
        public WeakReference<Bitmap> put( String key, WeakReference<Bitmap> value )
        {
            return super.put( key, value );
        }

        @Override
        protected boolean removeEldestEntry( LinkedHashMap.Entry<String, WeakReference<Bitmap>> eldest )
        {
            if( size() > SOFT_CACHE_CAPACITY )
            {
                Log.v( "tag", "Soft Reference limit , purge one" );
                if( eldest != null && eldest.getValue().get() != null )
                {
                    eldest.getValue().get().recycle();
                    return true;
                }
            }
            return false;
        }
    };

    //hard cache
    private final LruCache<String, Bitmap> sHardBitmapCache = new LruCache<String, Bitmap>( hardCachedSize )
    {
        @Override
        public int sizeOf( String key, Bitmap value )
        {
            return value.getRowBytes() * value.getHeight();
        }

        @Override
        protected void entryRemoved( boolean evicted, String key, Bitmap oldValue, Bitmap newValue )
        {
            Log.d( "memory cache", "hard cache is full , push to soft cache" );
            //硬引用缓存区满，将一个最不经常使用的oldvalue推入到软引用缓存区
            sSoftBitmapCache.put( key, new WeakReference<Bitmap>( oldValue ) );
        }
    };

    //软引用

    //缓存bitmap
    public boolean putBitmap( String key, Bitmap bitmap )
    {
        if( bitmap != null )
        {
            synchronized( sHardBitmapCache )
            {
                Log.d( "memory cache", "put bitmap into hard cache" );
                sHardBitmapCache.put( key, bitmap );
            }
            return true;
        }
        return false;
    }

    //从缓存中获取bitmap
    public Bitmap getBitmap( String key )
    {
        synchronized( sHardBitmapCache )
        {
            final Bitmap bitmap = sHardBitmapCache.get( key );
            if( bitmap != null )
                return bitmap;
        }
        //硬引用缓存区间中读取失败，从软引用缓存区间读取
        synchronized( sSoftBitmapCache )
        {
            WeakReference<Bitmap> bitmapReference = sSoftBitmapCache.get( key );
            if( bitmapReference != null )
            {
                final Bitmap bitmap2 = bitmapReference.get();
                if( bitmap2 != null )
                    return bitmap2;
                else
                {
                    Log.v( "memory cache", "soft reference has been recycled" );
                    sSoftBitmapCache.remove( key );
                }
            }
        }
        return null;
    }

}
